﻿using Application.Common.Extensions;
using Domain;
using Domain.Enums;
using Domain.Models.Cmd;
using MediatR;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Sockets;

namespace Application.Adapter
{
    public class CustomBetweenAndDataHandlingAdapter : CustomBetweenAndDataHandlingAdapter<BetweenAndRequestInfo>
    {
        public CustomBetweenAndDataHandlingAdapter()
        {
            this.MinSize = 3;//  若值设置过大，会一次解析多个包
        }

        public override byte[] StartCode => new byte[] { Consts.StartByte };//可以为0长度字节，意味着没有起始标识。

        public override byte[] EndCode => new byte[] { Consts.EndByte };//必须为有效值。

        protected override BetweenAndRequestInfo GetInstance()
        {
            return new BetweenAndRequestInfo();
        }
    }

    public class BetweenAndRequestInfo : IBetweenAndRequestInfo
    {

        /// <summary>
        /// 注意 body 已不包含收尾字节
        /// </summary>
        public byte[] Body { get; set; }
        /// <summary>
        /// 包含收尾字节
        /// </summary>
        public byte PackageLength { get; set; }

        public byte[] DeviceId { get; set; }

        public string deviceId { get; set; }
        public DataType DataType { get; set; }

        public bool VaildSuccess { get; set; }

        /// <summary>
        /// 不同命令所对应的类型数据
        /// </summary>
        public object Data { get; set; }

        /// <summary>
        /// 只做数据预处理不能中断请求
        /// </summary>
        /// <param name="body"></param>
        public void OnParsingBody(byte[] body)
         {
            var length = body.Length;
            this.Body = body;
            this.PackageLength = body[0];
            this.DeviceId = new byte[] { body[1], body[2], body[3], body[4] };
            this.deviceId = Convert.ToHexString(DeviceId);
            this.DataType = (DataType)body[5];
            this.VaildSuccess = body.VaildByte();
            //打印所有命令
            Console.WriteLine(nameof(OnParsingBody)+ Convert.ToHexString(body));
            ///设置data类型  方便api中直接获取到对象
            switch (this.DataType) 
            {
                case DataType.测试两个tcp:
                    break;
                case DataType.设备应答出酒命令上:
                    Data = new DeviceReplyOOWUp() { ChannelNumber = Convert.ToInt32(body[6]), RunState = Convert.ToInt32(body[7]) == 1 };
                    break;
                case DataType.出酒命令下:
                    break;
                case DataType.设备出酒完成上报上:
                    Data = new DeviceOOWEndUp() { ChannelNumber = Convert.ToInt32(body[6]), WineNumber = Convert.ToHexString(new byte[] { body[7], body[8] }).ByHexStringToInt32() };
                    break;
                case DataType.平台应答出酒完成上报下:
                    break;
                case DataType.设备暂停或继续出酒上报上:

                    Data = new DeviceOOWStopOrCountinueUp() { ChannelNumber = Convert.ToInt32(body[6]), OOWState = Convert.ToInt32(body[7]), OOWNumber = Convert.ToHexString(new byte[] { body[8], body[9] }).ByHexStringToInt32() };
                    break;
                case DataType.查询设备命令下:
                    break;
                case DataType.设备应答查询上:
                    Data = new DeviceReplySelect() { HaoDan = Convert.ToHexString(new byte[] { body[6], body[7], body[8], body[9] }), PowerSupply = Convert.ToInt32(body[10]), PowerNumber = Convert.ToInt32(body[11]) };
                    break;
                case DataType.设备开锁命令下:
                    break;
                case DataType.设备开锁应答上:
                    Data = new DeviceUnlock() { RunState = Convert.ToInt32(body[6]) };
                    break;
                case DataType.修改服务器IP下:
                    break;
                case DataType.修改IP应答上:
                    Data = new ModifyIpReply() { RunState = Convert.ToInt32(body[6]) };

                    break;
                case DataType.设备到服务器心跳包上:
                    break;
                case DataType.心跳包应答下:
                    break;
                case DataType.校准出酒命令下:
                    break;
                case DataType.校准出酒应答上:
                    Data = new CalibrationOOWReplyUp() { RunState = Convert.ToInt32(body[6]) };
                    break;
                case DataType.校准实际出酒命令下:
                    break;
                case DataType.校准实际出酒应答上:
                    Data = new CalibrateActuallyOOWReplyUp() { RunState = Convert.ToInt32(body[6]) };
                    break;
                case DataType.位置信息上报应答下:
                    break;
                case DataType.设备位置信息上报上:
                    var latLngLength = Convert.ToInt32(Body[0]) - 44;

                    var bodyStr = Convert.ToHexString(body);//4200F424011A3836393636353036313931303738323839383630344137313832314430313339393536283131332E3639393735332C33342E37343839303529CD
                    var imei = bodyStr.Skip(6 * 2).Take(15 * 2).ToArray().HexCharArrayToUTF8String();
                    var iccid = bodyStr.Skip(21 * 2).Take(20 * 2).ToArray().HexCharArrayToUTF8String();
                    var latLng = bodyStr.Skip(41 * 2).Take(latLngLength * 2).ToArray().HexCharArrayToUTF8String();
                    var lat = latLng.Split(",")[0].ToString();
                    var lng = latLng.Split(",")[1].ToString();
                    Data = new DevicePositionInfoUp() { IMEI = imei, ICCID = iccid, Lat = lat, Lng = lng };
                    break;
                case DataType.应答取消出酒命令下:
                    break;
                case DataType.取消出酒命令上:
                    Data = new CancelOOWUp() { ChannelNumber = Convert.ToInt32(body[6]) };
                    break;
                case DataType.更改设备ID号下:
                    break;
                case DataType.应答更改设备ID号上:
                    //
                    break;
                case DataType.远程升级固件下:
                    break;
                case DataType.远程升级固件应答上:
                    Data = new RemoteUpdateFirmwareReply() { Version = Convert.ToInt32(body[6]) };

                    break;
                case DataType.定时开关机下:
                    break;
                case DataType.定时开关机应答上:
                    Data = new SetTimerStopAndStartUp() { RunState = Convert.ToInt32(body[6]) };
                    break;
                case DataType.通道校准出酒下:
                    break;
                case DataType.通道校准出酒应答上:
                    Data = new ChannelCalibrateOOWReplyUp() { ChannelNumber = Convert.ToInt32(body[6]), RunState = Convert.ToInt32(body[7]) };
                    break;
                case DataType.通道校准时实际出酒命令下:
                    break;
                case DataType.通道校准时实际出酒应答上:
                    Data = new ChannelCalibActOOWReplyUp() { ChannelNumber = Convert.ToInt32(body[6]), RunState = Convert.ToInt32(body[7]) };
                    break;
                case DataType.通道刷卡上报命令:
                    Data = new ChannelSwipeCardToReportUp() { ChannelNumber = Convert.ToInt32(body[6]), CardNumber = Convert.ToHexString(new byte[] { body[7], body[8], body[9], body[10] }) };
                    break;
                case DataType.通道刷卡应答下:
                    break;
                case DataType.广告更新命令下:
                    break;
                case DataType.广告更新应答上:
                    Data = new AdUpdateReplyUp()
                    {
                        AdNumber = Convert.ToHexString(new byte[] { body[6], body[7] }).ByHexStringToInt32(),
                        RunState = Convert.ToInt32(body[8])
                    };
                    break;
                default:
                    break;
            }


            Console.WriteLine(this.DataType.ToString()+"::"+ JsonConvert.SerializeObject(Data));
        }

        public bool OnParsingEndCode(byte[] endCode)
        {
            return true;
        }

        public bool OnParsingStartCode(byte[] startCode)
        {
            return true;
        }
    }
}
